package com.epic.followup.service.wechat.impl;

import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.epic.followup.conf.FollowupStaticConfig;
import com.epic.followup.conf.PatientConfig;
import com.epic.followup.conf.WeChatConfig;
import com.epic.followup.model.app.AppPatientModel;
import com.epic.followup.repository.app.AppPatientRepository;
import com.epic.followup.service.wechat.WechatPatientService;
import com.epic.followup.temporary.DealMessageResponse;
import com.epic.followup.temporary.wechat.patient.WechatInformationRequest;
import com.epic.followup.temporary.wechat.patient.WechatInformationResponse;
import com.epic.followup.temporary.wechat.patient.WechatLoginbyCodeRequest;
import com.epic.followup.temporary.wechat.patient.WechatLoginbyCodeResponse;
import com.epic.followup.temporary.wechat.patient.WechatLoginbyPasswordRequest;
import com.epic.followup.temporary.wechat.patient.WechatRegisterRequest;
import com.epic.followup.util.DateTimeUtils;

import com.google.gson.JsonObject;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import net.jodah.expiringmap.ExpirationPolicy;
import net.jodah.expiringmap.ExpiringMap;

@Service
public class WechatPatientServiceImpl implements WechatPatientService {

    private ExpiringMap<String, String> loginCodeMap;// 登录验证码
    private ExpiringMap<String, String> resetCodeMap; // 重置密码验证码
    private ExpiringMap<String, String> registerCodeMap; // 注册验证码
    private org.slf4j.Logger log = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private AppPatientRepository appPatientRepository;
    @Autowired
    private WeChatConfig weChatConfig;

    public WechatPatientServiceImpl() {
        this.loginCodeMap = ExpiringMap.builder().maxSize(FollowupStaticConfig.MAX_USERNUM)
                .expiration(1, TimeUnit.MINUTES) // 1分钟有效
                .expirationPolicy(ExpirationPolicy.CREATED).variableExpiration().build();
        this.resetCodeMap = ExpiringMap.builder().maxSize(FollowupStaticConfig.MAX_USERNUM)
                .expiration(1, TimeUnit.MINUTES) // 1分钟有效
                .expirationPolicy(ExpirationPolicy.CREATED).variableExpiration().build();
        this.registerCodeMap = ExpiringMap.builder().maxSize(FollowupStaticConfig.MAX_USERNUM)
                .expiration(1, TimeUnit.MINUTES) // 1分钟有效
                .expirationPolicy(ExpirationPolicy.CREATED).variableExpiration().build();
    }

    @Override
    public DealMessageResponse sendRegisterCode(String tel) {
        DealMessageResponse res = new DealMessageResponse();
        if (this.registerCodeMap.get(tel) != null) {
            res.setErrorMsg("1分钟内已发送过验证码，请查收.");
            res.setErrorCode(502);
            return res;
        }

        // 测试代码
        String code = DateTimeUtils.generateCode();
        this.registerCodeMap.put(tel, code);
        if (!this.sendCode(tel, "SMS_183763062", code)) {
            res.setErrorMsg("短信发送失败，请联系网站管理员.");
            res.setErrorCode(502);
            return res;
        }

        res.setErrorCode(200);
        res.setErrorMsg("发送成功");
        return res;
    }

    @Override
    public DealMessageResponse sendLoginCode(String tel) {
        DealMessageResponse res = new DealMessageResponse();
        if (this.loginCodeMap.get(tel) != null) {
            res.setErrorMsg("1分钟内已发送过验证码，请查收.");
            res.setErrorCode(502);
            return res;
        }

        // 测试代码
        String code = DateTimeUtils.generateCode();
        this.loginCodeMap.put(tel, code);
        if (!this.sendCode(tel, "SMS_204106817", code)) {
            res.setErrorMsg("短信发送失败，请联系网站管理员.");
            res.setErrorCode(502);
            return res;
        }

        res.setErrorCode(200);
        res.setErrorMsg("发送成功");
        return res;
    }

    @Override
    public DealMessageResponse sendResetPasswordCode(String tel) {
        DealMessageResponse res = new DealMessageResponse();
        if (this.resetCodeMap.get(tel) != null) {
            res.setErrorMsg("1分钟内已发送过验证码，请查收.");
            res.setErrorCode(502);
            return res;
        }

        // 测试代码
        String code = DateTimeUtils.generateCode();
        this.resetCodeMap.put(tel, code);
        if (!this.sendCode(tel, "SMS_183770245", code)) {
            res.setErrorMsg("短信发送失败，请联系网站管理员.");
            res.setErrorCode(502);
            return res;
        }

        res.setErrorCode(200);
        res.setErrorMsg("发送成功");
        return res;
    }

    @Override
    public WechatLoginbyCodeResponse loginbyCode(WechatLoginbyCodeRequest req) {
        WechatLoginbyCodeResponse res = new WechatLoginbyCodeResponse();
        Optional<AppPatientModel> ou = appPatientRepository.findByTel(req.getTel());
        if (!ou.isPresent()) {
            res.setErrorMsg("用户不存在.");
            res.setErrorCode(504);
            return res;
        }
        AppPatientModel u = ou.get();
        if (loginCodeMap.get(u.getTel()) != null && loginCodeMap.get(u.getTel()).equals(req.getCode())) {
            res.setErrorMsg("登录成功");
            res.setErrorCode(200);
            res.setPassword(u.getPassword());
            return res;
        } else {
            res.setErrorMsg("验证码错误或已失效.");
            res.setErrorCode(505);
            return res;
        }
    }

    @Override
    public DealMessageResponse loginbyPassword(WechatLoginbyPasswordRequest req) {
        DealMessageResponse res = new DealMessageResponse();
        Optional<AppPatientModel> ob = appPatientRepository.findByTel(req.getTel());
        if (ob.isPresent()) {
            if (!req.getPassword().equals(ob.get().getPassword())) {
                res.setErrorCode(401);
                res.setErrorMsg("密码错误或账户不存在.");
                return res;
            }
        } else {
            res.setErrorCode(401);
            res.setErrorMsg("密码错误或账户不存在.");
            return res;
        }
        // 成功返回
        res.setErrorMsg("登录成功.");
        res.setErrorCode(200);
        return res;
    }

    @Override
    public DealMessageResponse register(WechatRegisterRequest req) {
        DealMessageResponse res = new DealMessageResponse();
        // 验证码校验
        if (this.registerCodeMap.get(req.getTel()) != null) {
            if (!req.getCode().equals(this.registerCodeMap.get(req.getTel()))) {
                res.setErrorCode(501);
                res.setErrorMsg("验证码不正确.");
                return res;
            }
        } else {
            res.setErrorCode(503);
            res.setErrorMsg("验证码不存在或已过期.");
            return res;
        }

        // 密码校验
        if (req.getPassword().equals("")) {
            res.setErrorCode(506);
            res.setErrorMsg("密码不能为空.");
            return res;
        }

        // 手机号是否已存在
        if (this.appPatientRepository.findByTel(req.getTel()).isPresent()) {
            res.setErrorCode(505);
            res.setErrorMsg("该手机号已注册.");
            return res;
        }
        AppPatientModel user = new AppPatientModel();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        user.setCreateTime(df.format(new Date()));
        user.setTel(req.getTel());
        user.setPassword(req.getPassword());
        appPatientRepository.save(user);
        res.setErrorMsg("注册成功.");
        res.setErrorCode(200);
        return res;
    }

    @Override
    public DealMessageResponse resetPassword(WechatRegisterRequest req) {
        DealMessageResponse res = new DealMessageResponse();
        Optional<AppPatientModel> ou = appPatientRepository.findByTel(req.getTel());
        if (!ou.isPresent()) {
            res.setErrorMsg("用户不存在.");
            res.setErrorCode(505);
            return res;
        }
        AppPatientModel u = ou.get();
        if (resetCodeMap.get(u.getTel()) != null && resetCodeMap.get(u.getTel()).equals(req.getCode())) {
            res.setErrorMsg("修改成功");
            res.setErrorCode(200);
            u.setPassword(req.getPassword());
            appPatientRepository.save(u);
            return res;
        } else {
            res.setErrorMsg("验证码错误或已失效.");
            res.setErrorCode(506);
            return res;
        }
    }

    @Override
    public DealMessageResponse setInformation(WechatInformationRequest req,String phone) {
        DealMessageResponse res = new DealMessageResponse();
        Optional<AppPatientModel> ou = appPatientRepository.findByTel(phone);
        if (!ou.isPresent()) {
            res.setErrorMsg("用户不存在.");
            res.setErrorCode(505);
            return res;
        }
        AppPatientModel u = ou.get();
        u.setUserName(req.getUserName());

        if (req.getImg() != null) {
            // 存储图像
            Base64.Decoder decoder = Base64.getDecoder();
            // 转换前端数据
            String imgStr = req.getImg().replaceAll(" ", "+");
            String img_path = "";
            if (imgStr.split(",")[0].equals("data:image/jpg;base64")) {
                String UUID = new Date().getTime() + ".jpg";
                img_path = PatientConfig.store_img + "/" + UUID;
                // 去除多余部分
                imgStr = imgStr.replace("data:image/jpg;base64,", "");
            } else {
                String UUID = new Date().getTime() + ".png";
                img_path = PatientConfig.store_img + "/" + UUID;
                // 去除多余部分
                imgStr = imgStr.replace("data:image/png;base64,", "");
            }
            try (FileOutputStream fos = new FileOutputStream(img_path);) {
                // 转换base64编码
                byte[] b = decoder.decode(imgStr);
                for (int i = 0; i < b.length; i++) {
                    if (b[i] < 0) {// 调整异常数据
                        b[i] += 256;
                    }
                }
                fos.write(b);
                fos.flush();
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 图像存储结束
            u.setImg(PatientConfig.img_query + img_path.split("/")[img_path.split("/").length - 1]);
        }
        u.setGender(PatientConfig.genders[req.getGender()]);
        u.setBirth(req.getBirth());
        u.setOccupation(req.getOccupation());
        u.setOccupationType(req.getOccupationType());
        u.setIsStudent(req.getIsStudent() == 0 ? "否" : "是");
        if (req.getIsStudent() != 0) {
            u.setUniversity(req.getUniversity());
            u.setCollege(req.getCollege());
            u.setMajor(req.getMajor());
        } else {
            u.setUniversity("");
            u.setCollege("");
            u.setMajor("");
        }
        u.setUserType(PatientConfig.userType[req.getUserType()]);
        if (req.getUserType() == 0) {
            u.setDiseaseType("");
            u.setPsychoStatus("");
            u.setHospital("");
            u.setDepartment("");
            u.setTherapist("");
        } else {
            u.setDiseaseType(PatientConfig.diseaseType[req.getDiseaseType()]);
            u.setPsychoStatus(PatientConfig.psychoStauts[req.getPsychoStatus()]);
            if (req.getPsychoStatus() == 0 || req.getPsychoStatus() == 1) {
                u.setHospital(PatientConfig.hospitals[req.getHospital()]);
                if (req.getHospital() == 0) {
                    u.setDepartment(req.getDepartment());
                    u.setTherapist(req.getTherapist());
                } else {
                    u.setDepartment("");
                    u.setTherapist("");
                }
            } else {
                u.setHospital("");
                u.setDepartment("");
                u.setTherapist("");
            }
        }
        appPatientRepository.save(u);
        res.setErrorMsg("修改成功");
        res.setErrorCode(200);
        return res;

    }

    @Override
    public WechatInformationResponse getInformation(String tel) {
        WechatInformationResponse res = new WechatInformationResponse();
        WechatInformationRequest information = new WechatInformationRequest();
        Optional<AppPatientModel> ou = appPatientRepository.findByTel(tel);
        if (!ou.isPresent()) {
            res.setErrorMsg("用户不存在.");
            res.setErrorCode(505);
            res.setInformation(information);
            return res;
        }
        AppPatientModel u = ou.get();
        //information.setTel(u.getTel());
        information.setImg(u.getImg());
        information.setUserName(u.getUserName());
        information.setGender(find_index(PatientConfig.genders, u.getGender()));
        information.setBirth(u.getBirth());
        information.setOccupation(u.getOccupation());
        information.setOccupationType(u.getOccupationType());
        information.setIsStudent("是".equals(u.getIsStudent()) ? 1 : 0);
        information.setUniversity(u.getUniversity());
        information.setCollege(u.getCollege());
        information.setMajor(u.getMajor());
        information.setUserType(find_index(PatientConfig.userType, u.getUserType()));
        information.setDiseaseType(find_index(PatientConfig.diseaseType, u.getDiseaseType()));
        information.setPsychoStatus(find_index(PatientConfig.psychoStauts, u.getPsychoStatus()));
        information.setHospital(find_index(PatientConfig.hospitals, u.getHospital()));
        information.setDepartment(u.getDepartment());
        information.setTherapist(u.getTherapist());

        res.setErrorMsg("查询成功");
        res.setErrorCode(200);
        res.setInformation(information);
        return res;
    }

    public int find_index(String[] array, String content) {
        for (int i = 0; i < array.length; i++) {
            if (array[i].equals(content)) {
                return i;
            }
        }
        return -1;
    }
    //更新患者信息
    @Override
    public void savePatient(AppPatientModel p){
        appPatientRepository.save(p);
    }

    // 根据手机号一键登录
    @Override
    public JSONObject wechatAutoLogin(String phoneNum) {
        Optional<AppPatientModel> ou = appPatientRepository.findByTel(phoneNum);
        JSONObject res=new JSONObject();
        if(!ou.isPresent()){
            res.put("label",ou.isPresent());
        }else{
            AppPatientModel u = ou.get();
            res.put("label",ou.isPresent());
            res.put("id",u.getId());
        }
        return res;
    }

    /*
     * 注册tempid : SMS_183763062 修改密码： SMS_183770245 验证码登录：SMS_204106817
     */
    public Boolean sendCode(String tel, String templateCode, String code) {
        DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", weChatConfig.getAli_access_key_id(),
                weChatConfig.getAli_access_key_secret());
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setSysMethod(MethodType.POST);
        request.setSysDomain("dysmsapi.aliyuncs.com");
        request.setSysVersion("2017-05-25");
        request.setSysAction("SendSms");
        request.putQueryParameter("RegionId", "cn-hangzhou");
        request.putQueryParameter("PhoneNumbers", tel);
        request.putQueryParameter("SignName", "迈思智能");
        request.putQueryParameter("TemplateCode", templateCode);
        request.putQueryParameter("TemplateParam", "{\"code\":\"" + code + "\"}");
        try {
            CommonResponse response = client.getCommonResponse(request);
            log.info(response.getData());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
}
